<?php
namespace Default;

use Zend\Mvc\ModuleRouteListener;
use Zend\Mvc\MvcEvent;
use Zend\ModuleManager\Feature\AutoloaderProviderInterface;
use Zend\Authentication\AuthenticationService;
use Zend\Authentication\Adapter\DbTable as DbTableAuthAdapter;
use Zend\Session\SessionManager;
use Zend\Session\Container;
use Zend\Db\ResultSet\ResultSet;
use Zend\Db\TableGateway\TableGateway;
use Zend\Stdlib\ArrayObject;
use Zend\Log\Writer\Stream;
use Zend\Log\Logger;
use ZB\Db\Mongo;

use User\Model\User;
use User\Model\UserTable;

class Module implements AutoloaderProviderInterface {

    public function getAutoloaderConfig() {
        return array(
            'Zend\Loader\StandardAutoloader' => array(
                'namespaces' => array(
                    'Base' => __DIR__ . '/src/Base',
                    'User' => __DIR__ . '/src/User'
                ),
            ),
            'Zend\Loader\ClassMapAutoloader' => array(
                __DIR__ . '/autoload_classmap.php',
            ),
        );
    }

    public function getConfig() {
        return include __DIR__ . '/config/module.config.php';
    }

//    public function init($moduleManager) {
//        $serviceManger = $moduleManager->getEvent()->getParam('ServiceManage');
//        $eventManager = $moduleManager->getEventManager();
//    }

    public function onBootstrap(MvcEvent $event) {
        $eventManager = $event->getApplication()->getEventManager();
//        $eventManager->attach(MvcEvent::EVENT_DISPATCH_ERROR, array($this,'onDispatchError'), 100);
        $moduleRouteListener = new ModuleRouteListener();
        $moduleRouteListener->attach($eventManager);
        $this->bootstrapSession($event);
        $this->bootstrapPhpSettings($event);
    }

    public function onDispatchError(MvcEvent $e) {
        $vm = $e->getViewModel();
        $vm->setTemplate('error/404');
    }

    private function bootstrapPhpSettings(MvcEvent $e) {
        $config = $e->getApplication()->getConfig();
        if (isset($config['phpSettings'])) {
            foreach ($config['phpSettings'] as $key => $value) {
                ini_set($key, $value);
            }
        }
    }

    private function bootstrapSession(MvcEvent $e) {
        $session = $e->getApplication()->getServiceManager()->get('Zend\Session\SessionManager');
        $session->start();
    }

    public function getTableGateway($sm, $tableOjb, $tableName) {
        $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
        $resultSetPrototype = new ResultSet();
        $resultSetPrototype->setArrayObjectPrototype($tableOjb);
        $tableGateway = new TableGateway($tableName, $dbAdapter, null, $resultSetPrototype);
        return $tableGateway;
    }

    public function getMongoConnection($sm) {
        $config = $sm->get('config');
        $connect = new Mongo($config['mongo']);
        return $connect;
    }

    public function getLogHandler($sm, $logType) {
        $config = $sm->get('config');
        $logger = false;
        if (isset($config['log'][$logType])) {
            $mode = null;
            if ($config['log'][$logType]['write_mode'] == 'append') {
                $mode = 'a';
            } elseif ($config['log'][$logType]['write_mode'] == 'overwrite') {
                $mode = 'w';
            }
            $writer = new Stream($config['log'][$logType]['write_path'], $mode);
            $logger = new Logger();
            $logger->addWriter($writer);
        }
        return $logger;
    }

    public function getServiceConfig() {
        $module = $this;
        return array(
            'factories'=>array(
                'Zend\Session\SessionManager' => function ($sm) {
                    $config = $sm->get('config');
                    if (isset($config['session'])) {
                        $session = $config['session'];

                        $sessionConfig = null;
                        if (isset($session['config'])) {
                            $class = isset($session['config']['class']) ? $session['config']['class'] : 'Zend\Session\Config\SessionConfig';
                            $options = isset($session['config']['options']) ? $session['config']['options'] : array();
                            $sessionConfig = new $class();
                            $sessionConfig->setOptions($options);
                        }

                        $sessionStorage = null;
                        if (isset($session['storage'])) {
                            $class = $session['storage'];
                            $sessionStorage = new $class();
                        }

                        $sessionManager = new SessionManager($sessionConfig, $sessionStorage, null);
                        if (isset($session['validators'])) {
                            $chain = $sessionManager->getValidatorChain();
                            foreach ($session['validators'] as $validator) {
                                $validator = new $validator();
                                $chain->attach('session.validate', array($validator, 'isValid'));
                            }
                        }
                    } else {
                        $sessionManager = new SessionManager();
                    }
                    Container::setDefaultManager($sessionManager);
                    return $sessionManager;
                },

                /* log service part start */
                'LogHandle' => function ($sm) use ($module) {
                    return $module->getLogHandler($sm, 'default');
                },
                /* log service part end */

                'User\Model\UserStorage' => function($sm){
                    return new \User\Model\UserStorage('reunion');
                },
                'Mongo\Connect' => function($sm) use ($module){
                    $connect = $module->getMongoConnection($sm);
                    return $connect;
                },
                'AuthService' => function($sm) {
                    $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
                    $dbTableAuthAdapter  = new DbTableAuthAdapter($dbAdapter, 'user','user_name','password', 'MD5(?)');
                    $authService = new AuthenticationService();
                    $authService->setAdapter($dbTableAuthAdapter);
                    $authService->setStorage($sm->get('User\Model\UserStorage'));
                    return $authService;
                },
                'User\Model\UserTable' =>  function($sm) use ($module) {
                    $tableGateway = $module->getTableGateway($sm, new User(), 'user');
                    $table = new UserTable($tableGateway);
                    return $table;
                },
                'User\Model\UserRole' =>  function($sm) use ($module) {
                    $tableGateway = $module->getTableGateway($sm, new ArrayObject(array(new UserRole(), new Resource()), 2), 'userrole');
                    $table = new UserRoleTable($tableGateway);
                    return $table;
                },
                'Data\Model\Mongo\DataTable' => function($sm) use ($module) {
                    $connect = $module->getMongoConnection($sm);
                    $table = new DataTable($connect);
                    return $table;
                },
            ),
        );
    }
}